package licode.unisop.types.event.impl;

import licode.unisop.types.event.DomainEvent;
import licode.unisop.types.event.DomainEventHandler;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class EventStoreDefault {

    private ConcurrentHashMap<String, EventStoreItem> events =
            new ConcurrentHashMap<>();

    public <T extends DomainEvent> void subscribe(Class<T> domainCls,
                                                       DomainEventHandler eventHandler) {
        EventStoreItem evh = events.computeIfAbsent(
                domainCls.getTypeName(), (key) -> new EventStoreItem(domainCls));
        evh.addHandler(eventHandler);
    }

    public <T extends DomainEvent> void publish(T event) {
        Class<?> currCls = event.getClass();
        List<EventStoreItem> evs = new ArrayList<>();
        String domainCls = DomainEvent.class.getTypeName();

        while (currCls != null) {
            EventStoreItem evh = events.get(currCls.getTypeName());
            currCls = currCls.getSuperclass();

            if (null != evh) {
                evs.add(evh);
            }

            if (currCls.getTypeName().equals(domainCls)) {
                break;
            }
        }

        if (evs.size() > 0) {
            for (EventStoreItem evh: evs) {
                for (DomainEventHandler handler : evh.getHandlers()) {
                    handler.handle(event);
                }
            }
        }
    }
}
